  package college;

import java.util.List;
import java.util.Random;

import javax.swing.text.DefaultEditorKit.CutAction;

import clientserver.Client;
import clientserver.Packet;
import clientserver.QueryResult;

/**
 * This class provides all functionality to control  change request treatment 
 * @author Maxim Rahman
 * @see collegeObject
 * @see Request
 * @see Client
 *
 */
public class RequestTreatment extends collegeObject {

	/*Request Stage Statuses
	 * ONLYADDED 0-  first stage in request treatment, in this stage IS director choose supervisor and committee  chairman 
	 NEWREQUEST 1- Request only added and evaluator randomly selected by system, waits for Supervisor accept
	 PRE_EVALUATOR 2-  Evaluator approved by Supervisor or selected another one,now Evaluator need to set up max stage time 
	 EVALUATOR_READY 3 - Evaluator set the max stage time --> need approval from Supervisor
	 EVALUATOR_RUN  4- Approval for stage time get, in other case  we back to PRE_EVALUATOR 
	 EVALUATOR_DONE  5- Evaluator stage done his report is ready, now we need chairman decision to continue
	 REPORT_REVIEW 6  - Waits for chairman input
	 ASKFORDETAILS 7 ( optional)- Chairman ask for additional details  from   Request Initiator 
		 ACCEPT_REPORT - 8 - Evalutator's report is accepted by the committee.
		 PRE_APPLYING 9 -  Change Request is accepted by chairman and commission, starting applying stage: 
		 ProcessLeader needed to set max stage time
		APPLYING_READY 10 -  Max Applying stage time is given, now waiting for Supervisor acceptance 
		APPLYING_RUN   11-  after  applying stage time is approved,  we waits from ProcessLeader Report
		APPLYING_DONE  12 - applying stage time is done :  Process Leader  put his  report in the system
	 	CLOSED_BY_COMMITTEE - 13 - Request has been rejected by the committee.
	 	TEST - 14 - Test the request changes.
	 	NOTIFY_INITIATOR - 15 - Send a message and await the approval of the initiator.
	 	TEST_APPROVED - 16- Test passed successfully. Request Closed succcesfully
	  
	  
	 */
	public static enum  RequestStage
	{
		ONLYADDED,NEWREQUEST,PRE_EVALUATOR,EVALUATOR_READY,EVALUATOR_RUN,EVALUATOR_DONE,REPORT_REVIEW,
		ASKFORDETAILS,ACCEPT_REPORT,
		PRE_APPLYING,APPLYING_READY,APPLYING_RUN,APPLYING_DONE,TESTING_RUN,TEST_OK,CLOSED_BY_COMMITTEE,TEST,NOTIFY_INITIATOR,TEST_APPROVED}	
	
	private int currentStage; // current stage of request treatment 
	private int rid;  // request id
	 private String responsible;  // login of  IS Engineer who is responsible for completing the current active stage
	 private String  start_date;
	 private String  end_date;
	 private String report;
	 private boolean  suspended;
	 
	
	 
	 /** constructor to call to add new request details to request_details table
	  * chooses  random evaluator for new request and set all request_details fields
	  * but only init all fields in ibject, but not save him to DB
	  * @param r -   new request in the system 
	  */
	public  RequestTreatment( Request r)   
	{
		rid=r.getId();       
		currentStage=0; // ONLYADDED
		client=	r.getClient();
		responsible=chooseRandomEvaluator();
	start_date=end_date="None";
	report=" ";
	suspended=false;

	
	}
	
	///////////////////////////////getters and setters///////////////////
	public String getStartDate()
	{
		return start_date;
	}
	
	
	public String getEndDate()
	{
		return end_date;
	}
	
	public void setStartDate(String s)
	{
	 start_date=s;
	}
	
	
	public void setEndDate(String s)
	{
		 end_date=s;
	}
	
	
	 
	/**
	 *  
	 * @return Evaluator of Request  if it's possible , otherwise returns null
	 */
	public String getEvaluator()
	{
		if(currentStage==1|currentStage==4|currentStage==2) return responsible;
		return "None";
	}
	
	
	/**
	 *  Use this constructor  when you need to  read request  from DB on server
	 * @param cl Connected with server  client, next function  im code in most cases is loadfromdb()
	 * @param id   Request id which will be will readed from DB
	 */
	public RequestTreatment(Client cl, int id) 
	
	{
		client=cl;
	rid=id;	
	}






	
	

	
	/**
	 *  load Request Processing details from the corresponding table in Database into the object
	 * could be used only after calling RequestTreatment( Client cl, int id) constructor
	 */
	public  void loadfromdb()
	{
		 if (client==null) return;
		String q="SELECT * FROM request_details WHERE id="+String.valueOf(rid);
System.out.println("q="+q);
		Packet p=new Packet(q);
		QueryResult qr= (QueryResult) client.SendPacketAndWait(p);
		responsible=qr.getString("responsibleactor");
		
		 start_date=qr.getString("start_date");
		
		  end_date=qr.getString("end_date");
report=qr.getString("details");	

String t=qr.getString("current_stage");
System.out.println("t="+t);
currentStage= Integer.parseInt(t);

if(currentStage>20)
	 suspended=true;

	 }
	
	
	
	
	
	/**
	 * Converts Requests fields  in String report about request
	 */
	public String toString()
	{
	
		String answ="\n"+GetStageDescription(currentStage)+
				"\n Stage start date:"+getStartDate()+
				"\n Stage end date:"+getEndDate()+
				"\nResponsible Information System Engineer: "+responsible;
		
		if(currentStage>1&currentStage!=20)answ=answ+"\nStage Report:"+report;
		return answ;
	}
	
	/**
	 * 
	 * @param stage -integer less than 20 for active steps or an integer greater than 20 for frozen stages 
	 * @return verbal description of the stage or when  the stage is frozen verbal description of the  request stage before freezing
	 */
	 public static String GetStageDescription( int  st)
	 
	 	 
	 {
		 String   desc="";
		 String status="";
		 if( st>20)
			 {status="Current  Request Status: Suspended.";
			 st-=20;
			 } else status="Current Request Status: Active.";
					 
					 RequestStage stage=RequestStage.values()[st];
		 switch(stage)
		 {
		 case ONLYADDED: desc="Request only added  Evaluator randomly cgooosed. Now IS Director need to choose supervisor  for handling this request";
		 case NEWREQUEST: desc="Supervisor needs to accept the evaluator for request"; break;
		 case PRE_EVALUATOR:desc="Evaluator acceped,  now he need to  setting the time for his stage execution  "; break;
		 case EVALUATOR_READY: desc="Time for stage is set by Evaluator. wait's for Supervisor approving for this deadline"; break;
		 case EVALUATOR_RUN:  desc="Evaluator Stage deadlines is approved by Supervisor. Waiting for  Evaluator report";break;
		 case EVALUATOR_DONE: desc=" Evaluator report is done. Now await's for comission with chairman desicion";break;
		 case ASKFORDETAILS: desc=" Commision ask from you to give more details about you preposition";break;
		 case PRE_APPLYING: desc=" Your change request is accepted by commision. Now Process Leader will set up his deadlines";break;
		 case APPLYING_READY: desc=" Process Leader set up Deadlines for applying stage and waits for Supervisor approving";break;
		 case APPLYING_RUN: desc= "after  applying stage time is approved, Process Leader starts his work and we waits for his report ";break;
		 case APPLYING_DONE: desc="Change Request is done by Process Leader.";break;
		 case TESTING_RUN:   desc=" tester  test the  work of Process Leader";break;
		 case TEST_OK:   	desc=" Test done. all ok.Your change Request  complete ";break;
		 }
		 
		 return status+"Stage Description "+desc;
		 
	 }
	 
	
	 
	 
	 
	/**
	 * change current stage in request handling 
	 * @param stage - new stage in  request handling
	 */
	 public void setcurrentstage(int stage)
	 {
		 currentStage=stage;
	 }
	 
	 /**
	  * update the current request stage status in Database could be used only after
	  * RequestTreatment( Client cl, int id) constructor
	  */
	 public void   updatestageindb()
	 {
		 if (client==null) return;
		String q="UPDATE request_details SET current_stage="+general.addapostrophs(String.valueOf(currentStage))+" WHERE id="+general.addapostrophs(String.valueOf(rid));
		Packet p= new Packet(q);
		p.setUpdatePacket();
		client.SendPacketNowait(p);
	 
	 
	 }
	 /**
	  * choose random evaluator from all IS engineers in IS department
	  * @return  random evaluator login for this request
	  */
	public String   chooseRandomEvaluator()
	{


		
		List<User> evals=User.GetUsersbyType(client, "ISE");

		java.util.Iterator<User>  it=evals.iterator();
int size= evals.size();
			Random r = new Random();
	 int randomel = r.nextInt(size)+1;

	 for( int i=1; i<randomel;i++)
	 {
	it.next();

	 } 
	 User ev=it.next();
	 return ev.getLogin();
			 
			  
	}
	
	/**
	 * Function will return the correct profession (String) for each set of start state and end state.
	 * @param s - Start state.
	 * @param e - End state
	 * @return String Profession.
	 */
	public String professionSelector(int s,int e){
		String prof;
		if (s == 0 && e ==1)
			prof = "Director";
		else
			if((s== 1 && e ==2) || (s ==9 && e == 10) || (s == 15 && e == 16) || (s == 3 && e == 4) || (s == 14 && e == 16))
				prof = "Supervisor";
			else
				if ((s == 2 && e == 3) || (s == 3 && e == 2) || (s == 4 && e == 5) || (s == 7 && e ==5))
					prof = "Evaluator";
				else
					if ((s == 5 && e == 6) || (s ==7 && e == 8) || (s == 9 && e == 13))
						prof = "Chairman";
					else
						if ((s == 6 && e == 7) || (s == 14 && e == 15))
							prof = "Initiator";
						else
							if ((s == 8 && e == 9) || (s == 10 && e == 11) || (s== 11 && e == 12))
										prof = "Process Leader";
									else
											if (s == 12 && e == 14)
												prof = "Tester";
											else
												prof = "Error";
		return prof;
	}
	/**
	 * save  current request treatment  request object as new row in DB
	 * 
	 */
	public void savecuruntstatetoDB()
	{
		String id=""+rid;
		int prevStage = RequestTreatment.getRequestStage(client, rid);
		String prof = professionSelector(prevStage,currentStage);
		String q;
		if (!prof.equals("Error"))
			responsible = prof;
		 q="INSERT INTO request_details (id,current_stage,start_date,end_date,responsibleactor,details) VALUES ("+general.addapostrophs(id)+","+general.addapostrophs(String.valueOf(currentStage))+","+general.addapostrophs(start_date)+","+general.addapostrophs(end_date)+","+general.addapostrophs(responsible)+","+general.addapostrophs(report)+")";

		Packet  p;
		p=new Packet(q);
		p.setUpdatePacket();

	
		client.SendPacketNowait(p);
		
	}
	
	
	/**
	 * update all fields of request Treatment in DB
	 */
	public void updatetoDB()
	{
		String id=""+rid;
	System.out.println("Responsible="+responsible);
		String q="UPDATE request_details SET current_stage="+general.addapostrophs(String.valueOf(currentStage))+",  start_date="+general.addapostrophs(start_date)+", end_date="+general.addapostrophs(end_date)+", responsibleactor="+general.addapostrophs(responsible)+",  details="+general.addapostrophs(report)+" WHERE id="+general.addapostrophs(String.valueOf(rid));
		System.out.println(q);
		
		Packet  p;
		p=new Packet(q);
		p.setUpdatePacket();

	
		client.SendPacketNowait(p);
		
	}

	 // static useful functions///////////////////////////////
	/**
	 * reads from DB all request wirh desired stage
	 * @param stage  - stage number to read from DB, number between 0 and 35 
	 * @param cl  - connected with server client object
	 * @return
	 */
	  public static QueryResult getallrequestsbystage( String stage, Client cl)
	  {
		  
		  RequestStage st= RequestStage.valueOf(stage);
	
		  int sti= st.ordinal();
		  String q="SELECT * FROM  request_details R  WHERE     R.current_stage="+general.addapostrophs(String.valueOf(sti));

			 Packet p=new Packet(q);

			   QueryResult res=(QueryResult) cl.SendPacketAndWait(p);
		  return res;
	  }
	  /**Static function toget request stage by jis id from DB
		  *  
		  * @param c  - connected with server client object 
		  * @param rid
		  * @return  number of current stage : 0-15 for active stages 20-35 for frozen stages
		  */
		 public static int getRequestStage(Client c,int rid)
		 {
			 RequestTreatment r= new RequestTreatment(c, rid);
			 r.loadfromdb();
			 
		 return r.getCurrentStage();
		 }
		 public int getCurrentStage()
		 {
			 return currentStage;
		 }  
		 
		 public static void setRequestStage(Client c,int rid,int newstage)
		 
		 {
			 RequestTreatment r= new RequestTreatment(c, rid);
			 r.loadfromdb();
			 
			 r.setcurrentstage(newstage);
			 r.updatestageindb();
		 }


	

	  
	
	
}
